package com.nd.fastdp.workflow.model.pojo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.nd.fastdp.framework.exception.BusinessException;
import com.nd.fastdp.framework.pojo.bo.LoginUser;
import com.nd.fastdp.utils.DateUtil;
import com.nd.fastdp.workflow.constant.ConditionType;
import com.nd.fastdp.workflow.constant.FieldTypes;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 流程中的一个节点
 */
@Data
public class Node implements Serializable {

    private String type; //节点类型
    private String nodeId;//节点ID
    private String content;//待接受审批人主管类型
    private Node childNode;
    private List<Node> conditionNodes;
    private Properties properties;

    private String prevId;//上级节点ID

    /**
     * 流线
     */
    public List<Node> flowline(String procdefCfgStr, Map<String, Object> flowVar, LoginUser loginUser) {

        List<Node> flowline = new ArrayList<Node>();

        JSONObject procdefCfg = JSON.parseObject(procdefCfgStr);

        Form form = JSONObject.parseObject(procdefCfg.getJSONObject("formData").toJSONString(), Form.class);

        form.setFiedls(JSONObject.parseArray(procdefCfg.getJSONObject("formData").getJSONArray("fields").toJSONString(), Field.class));

        //添加第一个节点
        flowline.add(this);

        if(this.getConditionNodes() != null && this.getConditionNodes().size() > 0){

            //添加条件中的节点
            appendCondition(form, this.getConditionNodes(), flowVar, loginUser, flowline);
        }

        //添加下一个节点
        if(this.getChildNode() != null){
            appendNext(form, this.getChildNode(), flowVar, loginUser, flowline);
        }

        return flowline;
    }

    private void appendCondition(Form form, List<Node> conditionNodeList, Map<String, Object> flowVar, LoginUser loginUser, List<Node> flowline){

        //匹配的条件节点
        Node matchNode = null;

        List<Condition> conditionList = null;
        for(Node conditionNode : conditionNodeList){

            //根据发起人判断
            if(conditionNode.getProperties().getInitiator() != null && !(conditionNode.getProperties().getInitiator() instanceof String)){//发起人不为空

                Map<String, JSONObject> deptMap = new HashMap<>();
                Map<String, JSONObject> userMap = new HashMap<>();

                JSONArray initiators = JSONObject.parseArray(JSON.toJSONString(conditionNode.getProperties().getInitiator()));

                for(Object obj : initiators){

                    JSONObject initiator = (JSONObject)obj;

                    //选择部门时判断当前登录的用户所属部门是否一致
                    if(StringUtils.isNotEmpty((String)initiator.get("deptId"))){
                        deptMap.put((String)initiator.get("id"), initiator);
                    }else{
                        userMap.put((String)initiator.get("id"), initiator);
                    }
                }

                //条件的发起人和所属部门皆不满足则返回
                if(deptMap.get(loginUser.getDept()) == null && userMap.get(loginUser.getUserId()) == null){
                    return;
                }
            }

            //根据条件判断
            conditionList = conditionNode.getProperties().getConditions();

            ConditionValue conditionValue = null;
            Boolean validFlag = true;
            for(Condition condition : conditionList){

                if(condition.getConditionValue() instanceof String){

                    if(!flowVar.get("field" + condition.getFormId()).equals(condition.getConditionValue())){
                        validFlag = false;
                        break;
                    }

                }else{

                    conditionValue = JSON.parseObject(JSON.toJSONString(condition.getConditionValue()), ConditionValue.class);

                    Double val = null;

                    Field field = form.findById(Integer.parseInt(condition.getFormId()));

                    if(field.getType().equals(FieldTypes.daterange.getValue())){

                        ArrayList<String> dateValues = (ArrayList<String>)flowVar.get("field" + condition.getFormId());

                        val = Double.valueOf(DateUtil.dateDiff(dateValues.get(0), dateValues.get(1)));

                    }else if(flowVar.get("field" + condition.getFormId()) instanceof String){
                        val = Double.parseDouble((String)flowVar.get("field" + condition.getFormId()));
                    }else{
                        validFlag = false;
                        break;
                    }


                    if(ConditionType.BET.equals(conditionValue.getType())){

                        List values = JSON.parseArray(JSON.toJSONString(conditionValue.getValue()), List.class);
                        Double first = (Double)(values.get(0));
                        Double last = (Double)(values.get(3));

                        //第一个数判断
                        if(ConditionType.LT.equals(values.get(1))){

                            if(first >= val){
                                validFlag = false;
                                break;
                            }

                        }else if(ConditionType.LTE.equals(values.get(1))){
                            if(first > val){
                                validFlag = false;
                                break;
                            }
                        }

                        //第二个数判断
                        if(ConditionType.GT.equals(values.get(3))){

                            if(last <= val){
                                validFlag = false;
                                break;
                            }

                        }else if(ConditionType.GTE.equals(values.get(3))){

                            if(last < val){
                                validFlag = false;
                                break;
                            }
                        }

                    }else{

                        Double thresholdVal = null;

                        if(conditionValue.getValue() instanceof Integer){
                            thresholdVal = Double.valueOf((Integer)conditionValue.getValue());
                        }else{
                            thresholdVal = (Double)conditionValue.getValue();
                        }


                        if(ConditionType.EQ.equals(conditionValue.getType())){

                            if(thresholdVal != val){
                                validFlag = false;
                                break;
                            }

                        }else if(ConditionType.LT.equals(conditionValue.getType())){

                            if(thresholdVal >= val){
                                validFlag = false;
                                break;
                            }

                        }else if(ConditionType.LTE.equals(conditionValue.getType())){

                            if(thresholdVal > val){
                                validFlag = false;
                                break;
                            }

                        }else if(ConditionType.GT.equals(conditionValue.getType())){

                            if(thresholdVal <= val){
                                validFlag = false;
                                break;
                            }

                        }else if(ConditionType.GTE.equals(conditionValue.getType())){

                            if(thresholdVal < val){
                                validFlag = false;
                                break;
                            }

                        }
                    }
                }
            }

            if(validFlag){
                matchNode = conditionNode;

                break;
            }

        }

        if(matchNode == null){
            throw new BusinessException("没有匹配的条件");
        }

        if(matchNode.getConditionNodes() != null && matchNode.getConditionNodes().size() > 0){
            appendCondition(form, matchNode.getConditionNodes(), flowVar, loginUser, flowline);
        }

        if(matchNode.getChildNode() != null){
            appendNext(form, matchNode.getChildNode(), flowVar, loginUser, flowline);
        }

    }

    private void appendNext(Form form, Node childNode, Map<String, Object> flowVar, LoginUser loginUser, List<Node> flowline){

        if(childNode == null){

            return;
        }

        flowline.add(childNode);

        if(childNode.getConditionNodes() != null && childNode.getConditionNodes().size() > 0){

            //添加条件中的节点
            appendCondition(form, childNode.getConditionNodes(), flowVar, loginUser, flowline);
        }

        //添加下一个节点
        if(childNode.getChildNode() != null){
            appendNext(form, childNode.getChildNode(), flowVar, loginUser, flowline);
        }
    }

    public static Node get(String nodeList, Integer step){

        return parseList(nodeList).get(step);
    }

    public static Boolean isEnd(String nodeList, Integer step){

        return parseList(nodeList).size() < step;
    }

    public static Node parse(String str) {
        return JSON.parseObject(str, Node.class);
    }

    public static List<Node> parseList(String str) {
        return JSON.parseArray(str, Node.class);
    }

    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }

}
